home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #11 / Amiga Plus CD - 2004 - No. 11.iso / AmiSoft / Dev / misc / LOCCounter.lha / LOCCounter / src / SourceCode.cpp < prev    next >
C/C++ Source or Header  |  2004-08-18  |  5KB  |  233 lines

  1. /****************************************************************************
  2. *
  3. * $RCSfile: SourceCode.cpp $
  4. * $Revision: 2.14 $
  5. * $Date: 2004/08/18 21:46:43 $
  6. * $Author: ssolie $
  7. *
  8. *****************************************************************************
  9. *
  10. * Copyright (c) 2004 Steven Solie.  All Rights Reserved.
  11. *
  12. *****************************************************************************
  13. *
  14. * SourceCode component
  15. */
  16. #include "SourceCode.h"
  17.  
  18. #include "FileCount.h"
  19. #include "File.h"
  20.  
  21. #include <exec/memory.h>
  22. #include <dos/dos.h>
  23. #include <utility/tagitem.h>
  24.  
  25. #include <proto/exec.h>
  26. #include <proto/dos.h>
  27.  
  28. #include <cctype>
  29. #include <cstring>
  30.  
  31.  
  32. SourceCode::SourceCode(FileCount& fc) :
  33.     m_file_count(fc),
  34.     m_in_comment(false),
  35.     m_source_buf(0),
  36.     m_source_size(0)
  37. {
  38.     m_line_buf[0] = '\0';
  39.     m_lines.reserve(250);
  40. }
  41.  
  42.  
  43. SourceCode::~SourceCode()
  44. {
  45.     if ( m_source_buf != 0 )  {
  46.         IExec->FreeMem(m_source_buf, m_source_size);
  47.     }
  48. }
  49.  
  50.  
  51. void SourceCode::load()
  52. {
  53.     File file;
  54.     file.open(m_file_count.getName(), MODE_OLDFILE);
  55.  
  56.     uint32 protection = file.getProtection();
  57.     if ( !(protection & FIBF_EXECUTE) )  {
  58.         IDOS->SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  59.         throw dos_error();
  60.     }
  61.  
  62.     m_source_size = file.getLength();
  63.     if ( m_source_size == 0 )  {
  64.         IDOS->SetIoErr(ERROR_OBJECT_WRONG_TYPE);
  65.         throw dos_error();
  66.     }
  67.  
  68.     m_source_size += 1;   // +1 for end-of-file terminator
  69.     m_source_buf = reinterpret_cast<char*>(
  70.         IExec->AllocMem(m_source_size, MEMF_ANY));
  71.     if ( m_source_buf == 0 )  {
  72.         throw std::bad_alloc();
  73.     }
  74.  
  75.     m_lines.clear();
  76.     char* source = m_source_buf;
  77.     try  {
  78.         while ( file.readString(m_line_buf, MAX_LINE_LEN) > 0 )  {
  79.             removeComments();
  80.             eatWhite();
  81.  
  82.             int32 line_len = std::strlen(m_line_buf);
  83.             if ( line_len > 0 )  {
  84.                 line_len += 1;    // +1 for '\0'
  85.                 IExec->CopyMem(m_line_buf, source, line_len);
  86.                 m_lines.push_back(source);
  87.                 source += line_len;
  88.             }
  89.         }
  90.     }
  91.     catch ( ... )  {
  92.         IExec->FreeMem(m_source_buf, m_source_size);
  93.         m_source_buf = 0;
  94.         throw;
  95.     }
  96. }
  97.  
  98.  
  99. void SourceCode::removeComments()
  100. {
  101.     if ( m_file_count.diffMode() )  {
  102.         if ( m_line_buf[0] != '<' && m_line_buf[0] != '>' )  {
  103.             m_line_buf[0] = '\0';
  104.         }
  105.         else  {
  106.             for ( uint32 i = 1;
  107.                   i < MAX_LINE_LEN && m_line_buf[i] != '\0';
  108.                   ++i )  {
  109.                 char* c0 = &m_line_buf[i];
  110.                 char* c1 = &m_line_buf[i+1];
  111.  
  112.                 if ( *c0 == '/' && (*c1 == '/' || *c1 == '*') )  {
  113.                     m_line_buf[0] = '\0';
  114.                     break;
  115.                 }
  116.                 else if ( *c0 == '*' )  {
  117.                     m_line_buf[0] = '\0';
  118.                     break;
  119.                 }
  120.                 else if ( !std::isspace(*c0) )  {
  121.                     break;
  122.                 }
  123.             }
  124.         }
  125.  
  126.         m_in_comment = false;    // no multi-line comments in diff mode
  127.     }
  128.  
  129.     for ( uint32 i = 0; i < MAX_LINE_LEN && m_line_buf[i] != '\0'; ++i )  {
  130.         char* c0 = &m_line_buf[i];
  131.         char* c1 = &m_line_buf[i+1];
  132.  
  133.         if ( m_in_comment )  {
  134.             if ( *c0 == '*' && *c1 == '/' )  {
  135.                 m_in_comment = false;
  136.                 *c0 = ' ';
  137.                 *c1 = ' ';
  138.             }
  139.             else  {
  140.                 *c0 = ' ';
  141.             }
  142.         }
  143.         else  {
  144.             if ( *c0 == '/' && *c1 == '/' )  {
  145.                 *c0 = '\0';
  146.                 break;
  147.             }
  148.             else if ( *c0 == '/' && *c1 == '*' )  {
  149.                 m_in_comment = true;
  150.                 *c0 = ' ';
  151.                 *c1 = ' ';
  152.             }
  153.         }
  154.     }
  155.  
  156.     m_line_buf[MAX_LINE_LEN - 1] = '\0';    // guarantee null termination
  157. }
  158.  
  159.  
  160. void SourceCode::eatWhite()
  161. {
  162.     // Convert all line feeds to nulls and white spaces to spaces
  163.     for ( uint32 i = 0; i < std::strlen(m_line_buf); ++i )  {
  164.         if ( m_line_buf[i] == '\n' )  {
  165.             m_line_buf[i] = '\0';
  166.         }
  167.         else if ( std::isspace(m_line_buf[i]) )  {
  168.             m_line_buf[i] = ' ';
  169.         }
  170.     }
  171.  
  172.     // Remove redundant white space
  173.     uint32 stretch = 0;
  174.     char* c = &m_line_buf[0];
  175.     while ( *c != '\0' )  {
  176.         if ( stretch > 0 )  {
  177.             if ( std::isspace(*c) )  {
  178.                 ++stretch;
  179.             }
  180.             else  {
  181.                 char* space = c - stretch;
  182.                 if ( stretch > 1 )  {
  183.                     std::strcpy(space + 1, c);     // +1 skips the space
  184.                 }
  185.  
  186.                 stretch = 0;
  187.             }
  188.         }
  189.         else  {
  190.             if ( std::isspace(*c) )  {
  191.                 ++stretch;
  192.             }
  193.         }
  194.  
  195.         ++c;
  196.     }
  197.  
  198.     // Remove trailing white space
  199.     for ( uint32 i = std::strlen(m_line_buf) - 1;
  200.           i >= 0 && std::isspace(m_line_buf[i]);
  201.           --i )  {
  202.         m_line_buf[i] = '\0';
  203.     }
  204.  
  205.     // Remove blank difference mode lines
  206.     if ( (m_line_buf[0] == '<' || m_line_buf[0] == '>') &&
  207.          std::strlen(m_line_buf) == 1)  {
  208.         m_line_buf[0] = '\0';
  209.     }
  210. }
  211.  
  212.  
  213. void SourceCode::count()
  214. {
  215.     if ( m_file_count.diffMode() )  {
  216.         for ( uint32 i = 0; i < m_lines.size(); ++i )  {
  217.             const char* line = m_lines.at(i);
  218.  
  219.             if ( m_file_count.diffMode() )  {
  220.                 if ( line[0] == '<' )  {
  221.                     m_file_count -= 1;
  222.                 }
  223.                 else if ( line[0] == '>' )  {
  224.                     m_file_count += 1;
  225.                 }
  226.             }
  227.         }
  228.     }
  229.     else  {
  230.         m_file_count += m_lines.size();
  231.     }
  232. }
  233.